#include "StatusGrpcClient.h"

StatusConPool::StatusConPool(size_t poolsize, string port, string host) :poolsize_(poolsize), host_(host), port_(port), b_stop_(false)
{
	for (int i = 0; i < poolsize_; i++)
	{
		std::shared_ptr<Channel> channel = grpc::CreateChannel(host_ + ":" + port_, grpc::InsecureChannelCredentials());
		connections_.push(StatusService::NewStub(channel));
	}
}

StatusConPool::~StatusConPool()
{
	std::lock_guard<std::mutex> lock(mutex);
	Close();
	while (!connections_.empty())
	{
		connections_.pop();
	}
}

std::unique_ptr<StatusService::Stub> StatusConPool::GetConnection()
{
	std::unique_lock<std::mutex> lock(mutex);
	cond_.wait(lock, [this]{
		if (b_stop_)
		{
			return true;
		}
		return !connections_.empty();
		});

	if (b_stop_)
	{
		return nullptr;
	}
	
	auto Status_ptr = std::move(connections_.front());
	connections_.pop();
	return Status_ptr;
}

void StatusConPool::ReturnConnection(std::unique_ptr<StatusService::Stub> con)
{
	std::lock_guard<std::mutex> lock(mutex);
	if (b_stop_)
	{
		return;
	}
	connections_.push(std::move(con));
	cond_.notify_one();
}

void StatusConPool::Close()
{
	b_stop_ = true;
	cond_.notify_all();
}

StatusGrpcClient::~StatusGrpcClient()
{
}

GetChatServerRsp StatusGrpcClient::GetChatServer(int uid)
{
	ClientContext context;
	GetChatServerReq request;
	request.set_uid(uid);
	GetChatServerRsp reply;

	auto con = pool_->GetConnection();

	Status status = con->GetChatServer(&context, request, &reply);
	Defer defer([this,&con]() {
		pool_->ReturnConnection(std::move(con));
		});

	if (status.ok())
	{
		return reply;
	}
	else
	{
		reply.set_error(ErrorCodes::RCP_faild);
		return reply;
	}
}

StatusGrpcClient::StatusGrpcClient()
{
	auto cfimgr = ConFigMgr::Inst();
	auto host = cfimgr["StatusServer"]["Host"];
	auto port = cfimgr["StatusServer"]["Port"];
	pool_.reset(new StatusConPool(5,port,host));
}
